package attr

import (
	"context"
	"gorm.io/gorm"
	"mall/common/excption"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"time"

	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type ModifyAttrLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewModifyAttrLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyAttrLogic {
	return &ModifyAttrLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ModifyAttrLogic) ModifyAttr(in *pb.ModifyAttrDTO) (*pb.EmptyObj, error) {
	// 1.check request dto
	attrMapper, checkErr := l.checkRequestDTO(in)
	if checkErr != nil {
		return nil, checkErr
	}
	// 2.builder entity
	attrEntity, categoryEntity := l.builderEntity(in)
	// 3.modify db
	saveErr := l.saveDB(attrMapper, attrEntity, categoryEntity)
	if saveErr != nil {
		return nil, saveErr
	}
	// 4.return obj
	return &pb.EmptyObj{}, nil
}

func (l *ModifyAttrLogic) saveDB(attrMapper *mapper.AttrMapper, attrEntity entity.AttrEntity,
	categoryEntity entity.AttrCategoryEntity) error {

	return l.svcCtx.DBEngin.Transaction(func(tx *gorm.DB) error {
		// 3.1 modify attr
		attrUpdateErr := attrMapper.UpdateCtx(tx, attrEntity)
		if attrUpdateErr != nil {
			return attrUpdateErr
		}
		// 3.2 modify category
		categoryMapper := mapper.NewAttrCategoryMapper(l.ctx)
		updateCategoryErr := categoryMapper.UpdateCtx(tx, categoryEntity)
		if updateCategoryErr != nil {
			return updateCategoryErr
		}
		return nil
	})
}

func (l *ModifyAttrLogic) builderEntity(in *pb.ModifyAttrDTO) (attrEntity entity.AttrEntity,
	categoryEntity entity.AttrCategoryEntity) {

	now := time.Now()
	attrEntity = entity.AttrEntity{
		UpdateTime: now,
		AttrId:     in.AttrId,
		ShopId:     in.ShopId,
		Name:       in.Name,
		Desc:       in.Desc,
		SearchType: int64(in.SearchType),
		AttrType:   int64(in.AttrType),
	}
	categoryEntity = entity.AttrCategoryEntity{
		CategoryId: in.CategoryId,
		UpdateTime: now,
		AttrId:     in.AttrId,
	}
	return attrEntity, categoryEntity
}

func (l *ModifyAttrLogic) checkRequestDTO(in *pb.ModifyAttrDTO) (*mapper.AttrMapper, error) {
	attrMapper := mapper.NewAttrMapper(l.ctx)
	attrBO := bo.AttrBO{
		AttrId: in.AttrId,
	}
	selectCountCtx, err := attrMapper.SelectCountCtx(l.svcCtx.DBEngin, attrBO)
	if err != nil {
		return nil, err
	}
	if selectCountCtx <= 0 {
		return nil, excption.NewErrCode(constans.AttrNotExistErr)
	}
	attrBO = bo.AttrBO{Name: in.Name, ShopId: in.ShopId}
	attrEntity, err := attrMapper.SelectOneCtx(l.svcCtx.DBEngin, attrBO)
	if err != nil {
		return nil, err
	}
	if attrEntity.AttrId > 0 && attrEntity.AttrId != in.AttrId {
		return nil, excption.NewErrCode(constans.AttrNameRepeatErr)
	}
	return attrMapper, nil
}
